package com.situ.util;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.alibaba.fastjson2.JSON;

/**
 * 封装一个继承了HttpServlet的父类 作为Controller通用的分发行为的处理方式 整合doGet 和 doPost行为
 * 通过固定的action参数来识别执行Controller中的哪个方法 (action的值就是方法的方法名
 * 普通controller只需要继承此父类，之后在controller中只需要写对应的业务方法就可以
 *  要求: 
 *  1普通的controller中不要使用方法重载
 * 2.action的值一定要对 
 * 3.业务方法中必须只有request和response两个参数? ?
 *
 */

public class BaseController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");

		// 接收一个行为参数
		//根据参数值判断要做哪个事件
		String action = request.getParameter("action");

		// 通过反射获取当前类中所有的声明的方法
		Method[] methods = this.getClass().getDeclaredMethods();
		//遍历所有方法 比较哪个方法的方法名与action一致，就执行哪个方法
		Method method = null;// 等循环完就保存上要执行的方法
		for (Method m : methods) {
			if (m.getName().equals(action)) {
				method = m;
			}
		}
		invokMethod(method, request, response);
	}

	// 接收一个方法，使用反射技术执行这个方法
	private void invokMethod(Method m, HttpServletRequest request, HttpServletResponse response) {
		try {

			// int count =m.getParameterCount();

			Parameter[] parameters = m.getParameters();// 获取方法的参数列表
			Class<?> types[] = m.getParameterTypes();// 获取m方法所有的参数的类型
			// 先创建一个长度对应原方法参数个数的空数组
			Object[] params = new Object[types.length];
			// 循环判断参数 ，根据类型放入对应类型的参数，打破固定两个参数的限制
			for (int i = 0; i < types.length; i++) {

				Parameter p = parameters[i];// 当次循环对应那个参数

				String pName = p.getName();// 获取这个参数的参数名

				if (types[i].equals(HttpServletRequest.class)) {
					params[i] = request;
				} else if (types[i].equals(HttpServletResponse.class)) {
					params[i] = response;
				} else {
					String value = request.getParameter(pName);
					if (types[i].equals(Integer.class)) {
						if (value != null && !"".equals(value)) {
							params[i] = Integer.parseInt(value);
						}
					} else if (types[i].equals(String.class)) {
						params[i] = value;
					} else if (types[i].equals(BigDecimal.class)) {
						 BigDecimal num = new BigDecimal(value);
						params[i] =num;
					} else if (types[i].equals(Double.class)) {
						params[i] = Double.parseDouble(value);
					} else if (types[i].equals(HttpSession.class)) {
						params[i] = request.getSession();
					} else if (types[i].equals(Date.class)) {
						if (value != null && !"".equals(value)) {
							SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
							try {
								params[i] = sdf.parse(value);
							}catch(Exception e){
								e.printStackTrace();
							}							
						}
					}else {//如果都不是，我认为应该是我们自己定义的一个类
						params[i] = makeObject(request,types[i]);
					}
				}
			}

			Object result = m.invoke(this, params);
			if (result != null) {// 反射执行controller中的方法时这个方法是有返回值的
				String str = JSON.toJSONString(result);
				response.setContentType("application/json;charset=UTF-8");
				PrintWriter pw = response.getWriter();
				pw.write(str);

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	
	public Object makeObject(HttpServletRequest request, Class<?> type) {
		try {
			Object o=type.newInstance();
			
			Enumeration<String> names= request.getParameterNames();//获取请求参数的名字
			
			while(names.hasMoreElements()) {//循环枚举所有的名字。返回false代表没有下一个
				String name =names.nextElement();//获取出当前这次循环的名字
				String value =request.getParameter(name);//此参数的值
				try {
					Field f=type.getDeclaredField(name);
					f.setAccessible(true);
					if(f.getType().equals(String.class)) {
						f.set(o, value);
					}else if(f.getType().equals(Integer.class)) {
						if(value!=null&&!"".equals(value)) {
							f.set(o, Integer.parseInt(value));
						}
						
					}else if(f.getType().equals(BigDecimal.class)) {
						if(value!=null&&!"".equals(value)) {
							f.set(o, new BigDecimal(value));
						}
						
					}else if(f.getType().equals(Date.class)) {
						if(value!=null&&!"".equals(value)) {
							SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
							try {
								f.set(o, sdf.parse(value));
							} catch (IllegalArgumentException | ParseException e) {
								e.printStackTrace();
							}
						}
						
					}
				} catch (NoSuchFieldException | SecurityException e) {
					
				}
			}
			
			return o;
		} catch (InstantiationException | IllegalAccessException e) {
			return null;
		}
		
	}
	
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}
